import asyncio
import time
import re
import json
from typing import Dict, Any
import httpx
from config.settings import (
    FEISHU_APP_ID,
    FEISHU_APP_SECRET,
    GRAPHIC_OUTLINE_TEMPLATE_URL
)

import logging
from app.utils.logger import get_logger

# 传入当前模块名，获取已配置好的日志器
logger = get_logger(__name__)


class FeishuSheetManager:
    """飞书表格管理器，处理表格创建、写入、链接返回"""

    # 修正：允许从外部传入folder_token，而非固定从配置读取
    def __init__(self, folder_token: str):
        self.app_id = FEISHU_APP_ID
        self.app_secret = FEISHU_APP_SECRET
        self.template_url = GRAPHIC_OUTLINE_TEMPLATE_URL
        self.template_token = self._extract_token_from_url(GRAPHIC_OUTLINE_TEMPLATE_URL)
        self.folder_token = folder_token  # 从外部传入的文件夹token
        self.timeout = 30.0
        self.client = httpx.AsyncClient(timeout=httpx.Timeout(30.0))
        self.tenant_access_token = None
        self.token_expire_time = 0  # 令牌过期时间（时间戳）
        logger.info("FeishuSheetManager 初始化完成")

    # 以下方法保持不变...
    def _extract_token_from_url(self, url: str) -> str:
        if not url:
            logger.error("飞书表格URL为空，无法提取token")
            return ""
        match = re.search(r'/sheets/([a-zA-Z0-9]+)', url)
        if match:
            token = match.group(1)
            logger.info(f"从URL中提取到表格token: {token}")
            return token
        else:
            logger.error(f"无法从URL中提取表格token: {url}")
            return ""

    async def get_tenant_access_token(self) -> str:
        current_time = time.time()
        if self.tenant_access_token and self.token_expire_time > current_time + 60:
            logger.info("使用缓存的tenant access token")
            return self.tenant_access_token
        try:
            logger.info("开始获取新的tenant access token")
            url = "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal"
            headers = {"Content-Type": "application/json; charset=utf-8"}
            payload = {
                "app_id": self.app_id,
                "app_secret": self.app_secret
            }
            response = await self.client.post(url, headers=headers, json=payload)
            response.raise_for_status()
            result = response.json()
            if result.get("code") != 0:
                error_msg = f"获取tenant access token失败: {result.get('msg')} (错误码: {result.get('code')})"
                logger.error(error_msg)
                raise Exception(error_msg)
            self.tenant_access_token = result.get("tenant_access_token")
            expire_in = result.get("expire_in", 3600)
            self.token_expire_time = current_time + expire_in
            logger.info(f"成功获取tenant access token，将在{expire_in}秒后过期")
            return self.tenant_access_token
        except httpx.HTTPError as e:
            error_msg = f"HTTP请求失败: {str(e)}"
            logger.error(error_msg)
            raise Exception(error_msg)
        except Exception as e:
            error_msg = f"获取tenant access token出错: {str(e)}"
            logger.error(error_msg)
            raise Exception(error_msg)

    # 关键修改1：接收外部传入的title，不再拼接“内容策略”后缀
    async def create_sheet_from_template(self, title: str) -> Dict[str, Any]:
        try:
            logger.info(f"开始创建表格: {title}")
            token = await self.get_tenant_access_token()
            url = f"https://open.feishu.cn/open-apis/drive/v1/files/{self.template_token}/copy"
            headers = {
                "Authorization": f"Bearer {token}",
                "Content-Type": "application/json; charset=utf-8"
            }
            # 核心：直接使用外部传入的title（达人名称），不添加额外后缀
            payload = {
                "name": title,  # 原逻辑：f"{title} - 内容策略"，现在去掉后缀
                "type": "sheet",
                "folder_token": self.folder_token  # 使用传入的folder_token
            }
            logger.info(f"创建表格请求: {url}")
            logger.info(f"创建表格参数: {payload}")
            async with httpx.AsyncClient(timeout=self.timeout) as client:
                response = await client.post(url, headers=headers, json=payload)
                logger.info(f"创建表格响应状态: {response.status_code}")
                if response.status_code >= 400:
                    error_msg = f"API请求失败 (状态码: {response.status_code}): {response.text}"
                    logger.error(error_msg)
                    return {"status": "error", "message": error_msg}
                result = response.json()
                logger.info(f"创建表格响应: {result}")
                if result.get("code") != 0:
                    error_msg = f"飞书接口错误: {result.get('msg')} (错误码: {result.get('code')})"
                    logger.error(error_msg)
                    return {"status": "error", "message": error_msg}
                if "data" not in result or "file" not in result["data"]:
                    error_msg = f"API返回格式异常: {result}"
                    logger.error(error_msg)
                    return {"status": "error", "message": error_msg}
                spreadsheet_data = result["data"]["file"]
                spreadsheet_token = spreadsheet_data.get("token")
                spreadsheet_url = spreadsheet_data.get("url")
                if not spreadsheet_token or not spreadsheet_url:
                    error_msg = f"缺少表格关键信息: {spreadsheet_data}"
                    logger.error(error_msg)
                    return {"status": "error", "message": error_msg}
                # 获取sheet_id
                meta_url = f"https://open.feishu.cn/open-apis/sheets/v2/spreadsheets/{spreadsheet_token}/metainfo"
                meta_response = await client.get(meta_url, headers=headers)
                meta_response.raise_for_status()
                meta_result = meta_response.json()
                if meta_result.get("code") != 0:
                    error_msg = f"获取sheet_id失败: {meta_result.get('msg')}"
                    logger.error(error_msg)
                    return {"status": "error", "message": error_msg}
                if not meta_result.get("data", {}).get("sheets"):
                    error_msg = "表格中未找到工作表"
                    logger.error(error_msg)
                    return {"status": "error", "message": error_msg}
                first_sheet = meta_result["data"]["sheets"][0]
                sheet_id = first_sheet.get("sheetId") or first_sheet.get("sheet_id") or "0"
                logger.info(f"成功创建表格: {spreadsheet_url}, sheet_id: {sheet_id}")
                return {
                    "status": "success",
                    "spreadsheet_token": spreadsheet_token,
                    "url": spreadsheet_url,
                    "sheet_id": sheet_id
                }
        except Exception as e:
            error_msg = f"创建表格出错: {str(e)}"
            logger.error(error_msg, exc_info=True)
            return {"status": "error", "message": error_msg}

    # 以下方法保持不变...
    async def fill_cells_in_sheet(self, spreadsheet_token: str, sheet_id: str, cell_data: Dict[str, str]) -> Dict[
        str, Any]:
        if not all(isinstance(x, str) for x in [spreadsheet_token, sheet_id]):
            error_msg = "spreadsheet_token或sheet_id不是字符串类型"
            logger.error(error_msg)
            return {"status": "error", "message": error_msg}
        if not isinstance(cell_data, dict):
            error_msg = "cell_data必须是字典类型"
            logger.error(error_msg)
            return {"status": "error", "message": error_msg}
        try:
            logger.info(f"开始向表格 {spreadsheet_token} 写入数据")
            logger.info(f"要写入的单元格数据: {cell_data}")
            token = await self.get_tenant_access_token()
            url = f"https://open.feishu.cn/open-apis/sheets/v2/spreadsheets/{spreadsheet_token}/values_batch_update"
            headers = {
                "Authorization": f"Bearer {token}",
                "Content-Type": "application/json; charset=utf-8"
            }
            value_ranges = []
            for cell, value in cell_data.items():
                if not isinstance(cell, str) or not isinstance(value, str):
                    logger.warning(f"跳过无效的单元格数据: {cell} -> {value}")
                    continue
                range_str = f"{sheet_id}!{cell}:{cell}"
                value_ranges.append({
                    "range": range_str,
                    "values": [[value]]
                })
            payload = {
                "valueRanges": value_ranges
            }
            logger.info(f"写入请求: {url}")
            logger.info(f"写入数据: {payload}")
            async with httpx.AsyncClient(timeout=self.timeout) as client:
                response = await client.post(url, headers=headers, json=payload)
                response.raise_for_status()
                result = response.json()
                logger.info(f"写入响应: {result}")
                if result.get("code") == 0:
                    logger.info("写入成功")
                    return {"status": "success", "message": "写入成功"}
                else:
                    error_msg = f"写入失败: {result.get('msg')}"
                    logger.error(error_msg)
                    return {"status": "error", "message": error_msg}
        except httpx.HTTPError as e:
            error_msg = f"写入失败: {str(e)}"
            if e.response is not None:
                error_msg += f"\n错误响应: {e.response.text}"
            logger.error(error_msg)
            return {"status": "error", "message": error_msg}
        except Exception as e:
            error_msg = f"写入失败: {str(e)}"
            logger.error(error_msg, exc_info=True)
            return {"status": "error", "message": error_msg}

    # 保持不变：接收title并传递给create_sheet_from_template
    async def create_and_write(self, title: str, cell_data: Dict[str, str]) -> Dict[str, Any]:
        create_result = await self.create_sheet_from_template(title)
        if create_result["status"] != "success":
            return create_result
        await asyncio.sleep(1)
        write_result = await self.fill_cells_in_sheet(
            spreadsheet_token=create_result["spreadsheet_token"],
            sheet_id=create_result["sheet_id"],
            cell_data=cell_data
        )
        if write_result["status"] != "success":
            return {
                "status": "error",
                "message": f"表格创建成功，但写入数据失败: {write_result.get('message')}",
                "url": create_result["url"]
            }
        return {
            "status": "success",
            "message": "表格创建并写入成功",
            "spreadsheet_url": create_result["url"],
            "spreadsheet_token": create_result["spreadsheet_token"]
        }


class FeishuSpreadsheetUtil:
    # 修正：初始化时接收folder_token，传递给FeishuSheetManager
    def __init__(self, folder_token: str):
        self.sheet_manager = FeishuSheetManager(folder_token=folder_token)
        logger.info("FeishuSpreadsheetUtil 初始化完成")

    # 关键修改2：新增sheet_title参数，接收外部传入的达人名称，替代内部生成的标题
    async def full_flow(self, sheet_title: str, video_script: str, strategy_result: str, shot_list: list = None) -> \
    Dict[str, Any]:
        try:
            logger.info("开始处理飞书表格流程（简化版本）")
            # 核心：使用外部传入的sheet_title（达人名称），不再内部生成标题
            cleaned_title = re.sub(r'[\\/*?:"<>|]', '-', sheet_title)  # 过滤非法字符
            if not cleaned_title.strip():
                cleaned_title = "未命名达人"  # 兜底：避免空标题
            logger.info(f"最终使用的表格标题: {cleaned_title}")

            # 单元格数据逻辑不变（仅写B8）
            cell_data = {
                "B8": strategy_result[:1000] if len(strategy_result) > 1000 else strategy_result,
            }
            logger.info(f"简化单元格数据: B8长度={len(cell_data['B8'])}")

            # 调用创建+写入，传递外部标题
            result = await self.sheet_manager.create_and_write(cleaned_title, cell_data)
            return result
        except Exception as e:
            error_msg = f"处理飞书表格时出错: {str(e)}"
            logger.error(error_msg, exc_info=True)
            return {"status": "error", "message": error_msg}
